﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using QLTT.Models;
using QLTT.Commands;
using System.Windows.Input;
using System.Text.RegularExpressions;
using QLTT.Properties;

namespace QLTT.ViewModels
{
    class AllStudentViewModel:WorkspaceViewModel, System.ComponentModel.IDataErrorInfo
    {
        private ObservableCollection<StudentViewModel> _lstStudentViewModel;
        private icanDataContext _dataContext;
        private DelegateCommand _findCommand;
        private DelegateCommand _addCommand;
        private DelegateCommand _deleteCommand;
        private DelegateCommand _registerClassAndFeeCommand;
        private DelegateCommand _manageStudentAbsenceCommand;
        private IQueryable<StudentViewModel> _query;
        private string _studentName;
        private string _sInvokeId;
        public AllStudentViewModel(icanDataContext dataContext)
        {
            _lstStudentViewModel = new ObservableCollection<StudentViewModel>();
            _dataContext = dataContext;
            this.Class = 0;
            base.DisplayName = Properties.Resources.Base_DisplayName_AllStudent;
        }
        public AllStudentViewModel(icanDataContext dataContext, bool isGetAll)
        {
            _lstStudentViewModel = new ObservableCollection<StudentViewModel>();
            _dataContext = dataContext;
            if (isGetAll)
            {
                _query = from oStudent in _dataContext.Students orderby oStudent.ID descending select new StudentViewModel(_dataContext, oStudent);
                this.NumRow = _query.Count();
                this.CurPage = 1;
                this.UpdateList();
            }
            
            this.Status = Properties.Resources.Combo_AllClass_Status_Default;
            base.DisplayName = Properties.Resources.Base_DisplayName_AllStudent;
        }
        public AllStudentViewModel(icanDataContext dataContext, long lClassId)
        {
            _lstStudentViewModel = new ObservableCollection<StudentViewModel>();
            _dataContext = dataContext;
            //List<long> lstStudentId = _dataContext.StudentClasses.Where(o => o.Class == lClassId).Select(o => o.Student);
            //_query = from oStudent in _dataContext.Students.Where( select new StudentViewModel(_dataContext, oStudent);
            //this.NumRow = _query.Count();
            //this.CurPage = 1;
            //this.UpdateList()
            this.Status = Properties.Resources.Combo_AllClass_Status_Default;
            this.Class = lClassId;
            base.OnPropertyChanged("Class");
            Find();
            base.DisplayName = Properties.Resources.Base_DisplayName_AllStudent;
        }
        public string Name
        {
            get { return _studentName; }
            set { _studentName = value; }
        }
        public string InvokeId
        {
            get { return _sInvokeId; }
            set { _sInvokeId = value; }
        }
        public long Class { get; set; }
        public string Status { get; set; }
        public List<ClassViewModel> Classes
        {
            get
            {
                List<ClassViewModel> lstClass = _dataContext.Classes.OrderByDescending(cls => cls.StartDate).Select(cls => new ClassViewModel(_dataContext, cls)).ToList();
                ClassViewModel clsvm = new ClassViewModel(_dataContext);
                clsvm.Name = QLTT.Properties.Resources.Combo_AllStudent_Class_Default;
                lstClass.Insert(0, clsvm);
                return lstClass;
            }
        }
        public string[] Statuses
        {
            get
            {
                return new string[]
                {
                    Properties.Resources.Combo_AllClass_Status_Default,
                    Properties.Resources.Combo_AllStudent_Status_NotPayFee,
                    Properties.Resources.Combo_AllStudent_Status_HasPayFee
                };
            }
        }
        public ObservableCollection<StudentViewModel> AllStudents
        {
            get { return _lstStudentViewModel; }
            set {
                _lstStudentViewModel = value;
                base.OnPropertyChanged("AllStudents");
            }
        }
        public ICommand FindCommand
        {
            get
            {
                if (_findCommand == null)
                {
                    _findCommand = new DelegateCommand(Find);
                }
                return _findCommand;
            }
        }
        public ICommand AddCommand
        {
            get
            {
                if (_addCommand == null)
                {
                    _addCommand = new DelegateCommand(AddStudent);
                }
                return _addCommand;
            }
        }
        public ICommand DeleteCommand
        {
            get
            {
                if (_deleteCommand == null)
                {
                    _deleteCommand = new DelegateCommand(DeleteStudent, CanDeleteStudent);
                }
                return _deleteCommand;
            }
        }
        public bool CanDeleteStudent()
        {
            if (ViewModelBase.CurrentRole != UserRole.Administrator)
                return false;
            return false;
        }
        public ICommand RegisterClassAndFeeCommand
        {
            get
            {
                if (_registerClassAndFeeCommand == null)
                {
                    _registerClassAndFeeCommand = new DelegateCommand(RegisterClassAndFee);
                }
                return _registerClassAndFeeCommand;
            }
        }
        public ICommand ManageStudentAbsenceCommand
        {
            get
            {
                if (_manageStudentAbsenceCommand == null)
                {
                    _manageStudentAbsenceCommand = new DelegateCommand(ManageStudentAbsence);
                }
                return _manageStudentAbsenceCommand;
            }
        }
        public void Find()
        {
            IQueryable<Student> myQuery = _dataContext.Students;
            if (!string.IsNullOrEmpty(_studentName))
                myQuery = myQuery.Where<Student>(oStudent => oStudent.Name.Contains(_studentName));
            //Add more Where Conditions here
            if (this.Class > 0)
            {
                var qStudentClass = _dataContext.StudentClasses.Where(sclass => sclass.Class == this.Class);
                List<long> lstStudentId = qStudentClass.Select(sStudent => sStudent.Student).ToList();
                myQuery = myQuery.Where(oStudent => lstStudentId.Contains(oStudent.ID));
            }
            if (this.Status != Properties.Resources.Combo_AllClass_Status_Default)
            {
                if (this.Status == Properties.Resources.Combo_AllStudent_Status_NotPayFee)
                {
                    List<long> lDebtStudentIds = GetListDebtStudent();
                    myQuery = myQuery.Where(oStudent => lDebtStudentIds.Contains(oStudent.ID));
                }
            }
            if (!string.IsNullOrEmpty(_sInvokeId))
            {
                double dInvokeId = 0;
                if (double.TryParse(_sInvokeId, out dInvokeId))
                {
                    long studentId = _dataContext.FeePayments.Where(o => o.ID == double.Parse(_sInvokeId)).Select(o => o.Student).FirstOrDefault();
                    if (studentId > 0)
                        myQuery = myQuery.Where(oStudent => oStudent.ID == studentId);
                }
            }
            //Order
            myQuery = myQuery.OrderByDescending(oStudent => oStudent.ID);
            //Select

            _query = myQuery.Select(oStudent => new StudentViewModel(_dataContext, oStudent));
            this.NumRow = _query.Count();
            //Reset to page 0
            this.CurPage = 1;
            this.UpdateList();
        }
        public void AddStudent()
        {
            StudentViewModel ws = new StudentViewModel(_dataContext);
            Mediator.NotifyColleagues<WorkspaceViewModel>(Messages.WorkspaceAdd, ws);
        }
        private void DeleteStudent()
        {
            foreach (StudentViewModel svm in AllStudents)
            {
                if (svm.IsSelected)
                {
                    var oStudent = _dataContext.Students.First(t => t.ID == svm.ID);
                    if(oStudent != null)
                        _dataContext.Students.DeleteOnSubmit(oStudent);
                }
            }
            _dataContext.SubmitChanges();
            this.NumRow = _query.Count();
            this.UpdateList();

        }
        private void RegisterClassAndFee()
        {
            foreach (StudentViewModel svm in AllStudents)
            {
                if (svm.IsSelected)
                {
                    Student oStudent = _dataContext.Students.First(t => t.ID == svm.ID);
                    StudentClassFeeViewModel studentClassFeeViewModel = new StudentClassFeeViewModel(_dataContext, oStudent);
                    Mediator.NotifyColleagues<WorkspaceViewModel>(Messages.WorkspaceAdd, studentClassFeeViewModel);
                    return;
                }
            }
        }
        private void ManageStudentAbsence()
        {
            foreach (StudentViewModel svm in AllStudents)
            {
                if (svm.IsSelected)
                {
                    Student oStudent = _dataContext.Students.First(t => t.ID == svm.ID);
                    AllAbsenceViewModel allAbesenceViewModel = new AllAbsenceViewModel(_dataContext, oStudent);
                    Mediator.NotifyColleagues<WorkspaceViewModel>(Messages.WorkspaceAdd, allAbesenceViewModel);
                    return;
                }
            }
        }
        [MediatorLib.MediatorMessageSink(Messages.ListStudentUpdated, ParameterType = typeof(Student))]
        public void UpdateListStudent(Student oStudent)
        {
            this.NumRow = _query.Count();
            this.UpdateList();
        }

        public override void UpdateList()
        {
            List<StudentViewModel> lstStudents = _query.Skip((this.CurPage - 1) * this.RowsPerPage).Take(this.RowsPerPage).ToList();
            AllStudents = new ObservableCollection<StudentViewModel>(lstStudents);
            base.UpdateList();
        }
        private List<long> GetListDebtStudent()
        {
            List<long> lStudentIds = _dataContext.Students.Select(o => o.ID).ToList();
            List<long> lResultIds = new List<long>();
            foreach (long lStudentId in lStudentIds)
                if (IsDebtStudent(lStudentId))
                    lResultIds.Add(lStudentId);
            return lResultIds;
        }
        private bool IsDebtStudent(long lStudentId)
        {
            //Nho kiem tra trang thai sinh vien, neu da nghi? hoc ko xem la no*.
            var query = _dataContext.StudentClasses.Where(o => o.Class1.StartDate < DateTime.Now);
            query =query.Where(o => o.Student == lStudentId);
            List<StudentClass> oStudentClasses = query.Select(o => o).ToList();
            foreach (StudentClass oStudentClass in oStudentClasses)
            {
                //Kiem tra, dam bao sinh vien van con hoc lop nay
                if (oStudentClass.Status==0)
                    if (IsDebtStudentInClass(oStudentClass)) return true;   
            }
            return false;
        }
        private bool IsDebtStudentInClass(StudentClass oStudentClass)
        {
            List<byte> bMonths = _dataContext.FeePayments.Where(o => o.Student == oStudentClass.Student).Where(o => o.Class == oStudentClass.Class).Select(o => o.Months).ToList();
            int iNumMonths = 0;
            foreach (byte bMonth in bMonths)
                iNumMonths += bMonth;
            return (oStudentClass.Class1.StartDate.AddMonths(iNumMonths) <= DateTime.Now ? true : false);
        }
        #region IDataErrorInfo Members

        public string Error
        {
            get { return null; }
        }

        public string this[string property]
        {
            get
            {
                string msg = null;
                Regex rxValidate;
                switch (property)
                {
                    case "InvokeId":
                        rxValidate = new Regex(@"\d+", RegexOptions.Singleline);
                        if (!rxValidate.IsMatch(this.InvokeId))
                            msg = Resources.ValidationInvokeIdError;
                        break;
                    default:
                        throw new ArgumentException(
                            Resources.ValidationDefaultException_Error + property);
                }
                return msg;
            }
        }

        #endregion // IDataErrorInfo Members
    }
}
